package com.ticket.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ticket.entity.SeatAllocation;
import com.ticket.mapper.SeatAllocationMapper;
import com.ticket.service.ISeatAllocationService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class SeatAllocationServiceImpl extends ServiceImpl<SeatAllocationMapper, SeatAllocation> implements ISeatAllocationService {

    @Override
    @Transactional
    public void initializeSeatAllocations(Long matchId, Long sectionId, Integer capacity) {
        // 检查是否已经初始化
        LambdaQueryWrapper<SeatAllocation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SeatAllocation::getMatchId, matchId)
                   .eq(SeatAllocation::getSectionId, sectionId);

        long count = this.count(queryWrapper);
        if (count > 0) {
            return; // 已经初始化过了
        }

        // 批量插入座位分配记录
        List<SeatAllocation> allocations = new ArrayList<>();
        for (int i = 1; i <= capacity; i++) {
            SeatAllocation allocation = new SeatAllocation();
            allocation.setMatchId(matchId);
            allocation.setSectionId(sectionId);
            allocation.setSeatNumber(i);
            allocation.setStatus("AVAILABLE");
            allocations.add(allocation);
        }

        this.saveBatch(allocations);
    }

    @Override
    public List<Integer> getOccupiedSeats(Long matchId, Long sectionId) {
        LambdaQueryWrapper<SeatAllocation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SeatAllocation::getMatchId, matchId)
                .eq(SeatAllocation::getSectionId, sectionId)
                .in(SeatAllocation::getStatus,"SOLD", "RESERVED");

        return this.list(queryWrapper).stream()
                .map(SeatAllocation::getSeatNumber)
                .collect(Collectors.toList());
    }

    @Override
    public Integer getNextAvailableSeat(Long matchId, Long sectionId) {
        // 获取区域容量
        Integer capacity = baseMapper.getSectionCapacity(sectionId);
        if (capacity == null) {
            return null;
        }

        // 获取已占用座位
        List<Integer> occupiedSeats = getOccupiedSeats(matchId, sectionId);

        // 如果所有座位都已分配，返回null
        if (occupiedSeats.size() >= capacity) {
            return null;
        }

        // 找到最小的未分配座位号
        for (int i = 1; i <= capacity; i++) {
            if (!occupiedSeats.contains(i)) {
                return i;
            }
        }

        return null;
    }

    @Override
    @Transactional
    public boolean updateSeatStatus(Long matchId, Long sectionId, Integer seatNumber, String status) {
        LambdaUpdateWrapper<SeatAllocation> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(SeatAllocation::getMatchId, matchId)
                    .eq(SeatAllocation::getSectionId, sectionId)
                    .eq(SeatAllocation::getSeatNumber, seatNumber)
                    .set(SeatAllocation::getStatus, status);

        return this.update(updateWrapper);
    }

    @Override
    public boolean allocateSeat(Long matchId, Long sectionId, Integer seatNumber, String status) {
        // 检查座位是否已被分配
        LambdaQueryWrapper<SeatAllocation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SeatAllocation::getMatchId, matchId)
                .eq(SeatAllocation::getSectionId, sectionId)
                .eq(SeatAllocation::getSeatNumber, seatNumber);

        if (this.count(queryWrapper) > 0) {
            return this.updateSeatStatus(matchId, sectionId, seatNumber, status);
        }

        // 分配新座位
        SeatAllocation seatAllocation = new SeatAllocation();
        seatAllocation.setMatchId(matchId);
        seatAllocation.setSectionId(sectionId);
        seatAllocation.setSeatNumber(seatNumber);
        seatAllocation.setStatus(status);

        return this.save(seatAllocation);
    }

    @Override
    public boolean releaseSeat(Long matchId, Long sectionId, Integer seatNumber) {
        return this.updateSeatStatus(matchId, sectionId, seatNumber, "AVAILABLE");
    }

    @Override
    public Integer getSoldSeatCount(Long matchId, Long sectionId) {
        LambdaQueryWrapper<SeatAllocation> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SeatAllocation::getMatchId, matchId)
                .eq(SeatAllocation::getSectionId, sectionId)
                .in(SeatAllocation::getStatus, "SOLD", "RESERVED");

        return Math.toIntExact(this.count(queryWrapper));
    }
}
